package com.gitee.wsl.transform.validator.string

import com.gitee.wsl.struct.combine.BCombinedTModifier
import com.gitee.wsl.text.format.format
import com.gitee.wsl.text.reader.MicroStrReader
import com.gitee.wsl.transform.validator.ValidationError
import com.gitee.wsl.transform.validator.Validator
import com.gitee.wsl.transform.validator.validateWithResult


fun interface StringValidator: Validator<String, StringValidator> {

    override fun self(): StringValidator = this

    override infix fun then(other: StringValidator): StringValidator
        = if (other === StringValidator) this else StringValidatorBCombinedTModifier(this, other)

    companion object:StringValidator{
        override fun then(other: StringValidator) = other

        override fun validate(para: String): Boolean = false

        override fun <R> foldIn(initial: R, operation: (R, StringValidator) -> R): R = initial

        override fun <R> foldOut(initial: R, operation: (StringValidator, R) -> R): R = initial

        override fun any(predicate: (StringValidator) -> Boolean): Boolean = false

        override fun all(predicate: (StringValidator) -> Boolean): Boolean = true
    }
}

class StringValidatorBCombinedTModifier(outer: StringValidator,
                                        inner: StringValidator):
    BCombinedTModifier<StringValidator>(outer,inner),StringValidator{
    override fun validate(para: String): Boolean = false
}

fun StringValidator.then(message:String,block:(para: String)->Boolean) = then(stringValidator(message,block))

fun String.validate(validator:StringValidator) =  validator.foldIn(true){ flag, v->
    if(v.validate(this)) true else return@foldIn false
}

fun String.validateWithMessage(validator:StringValidator)
   = validator.validateWithResult(this)


internal fun stringValidator(message: String,checkBlock:(String)->Boolean)  = object : StringValidator{

    override fun message(para: String): ValidationError = ValidationError.Generic(String.format(message,para))

    override fun validate(para: String): Boolean = checkBlock(para)
}

fun MicroStrReader.tryRead(rules: StringValidator) = tryReadString { rules(it.toString()) }

